package com.jzo2o.health.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.jzo2o.common.expcetions.CommonException;
import com.jzo2o.common.expcetions.DBException;
import com.jzo2o.common.utils.CollUtils;
import com.jzo2o.health.mapper.ReservationSettingMapper;
import com.jzo2o.health.model.domain.ReservationSetting;
import com.jzo2o.health.model.dto.request.ReservationSettingUpsertReqDTO;
import com.jzo2o.health.model.dto.response.ReservationDateResDTO;
import com.jzo2o.health.model.dto.response.ReservationSettingResDTO;
import com.jzo2o.health.model.excel.ReservationImportData;
import com.jzo2o.health.service.IReservationSettingService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.YearMonth;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 * @author JIAN
 */
@Service
public class ReservationSettingServiceImpl extends ServiceImpl<ReservationSettingMapper, ReservationSetting> implements IReservationSettingService {
    @Override
    @SuppressWarnings("unchecked")
    public List<ReservationSettingResDTO> getReservationSettingByMonth(YearMonth yearMonth) {
        List<ReservationSetting> reservationSettingList = lambdaQuery()
                .ge(ReservationSetting::getOrderDate, yearMonth.atDay(1))
                .le(ReservationSetting::getOrderDate, yearMonth.atEndOfMonth())
                .orderByDesc(ReservationSetting::getOrderDate)
                .list();

        if (CollUtils.isEmpty(reservationSettingList)) {
            return new ArrayList<>();
        } else {
            return reservationSettingList.stream()
                    .map(item -> ReservationSettingResDTO.builder()
                            .date(item.getOrderDate().toString())
                            .number(item.getNumber())
                            .reservations(item.getReservations())
                            .build())
                    .collect(Collectors.toList());
        }
    }

    @Override
    public void editNumberByDate(ReservationSettingUpsertReqDTO reservationSettingUpsertReqDTO) {
        LocalDate orderDate = reservationSettingUpsertReqDTO.getOrderDate();
        Integer number = reservationSettingUpsertReqDTO.getNumber();

        Optional.ofNullable(lambdaQuery()
                        .eq(ReservationSetting::getOrderDate, orderDate)
                        .one())
                .ifPresentOrElse(reservationSetting -> {
                    // 存在则更新
                    if (!lambdaUpdate()
                            .eq(ReservationSetting::getOrderDate, orderDate)
                            .set(ReservationSetting::getNumber, number)
                            .update()) {
                        throw new DBException("更新预约设置表失败");
                    }
                }, () -> {
                    // 不存在则创建
                    if (!SqlHelper.retBool(baseMapper.insert(ReservationSetting
                            .builder()
                            .orderDate(orderDate)
                            .reservations(0)
                            .number(number)
                            .build()))) {
                        throw new DBException("插入预约设置表失败");
                    }
                });
    }

    @Override
    @Transactional
    public void editNumberByDateBatch(List<ReservationImportData> reservationDataList) {
        for (ReservationImportData reservationData : reservationDataList) {
            this.editNumberByDate(ReservationSettingUpsertReqDTO.builder()
                    .orderDate(LocalDate.parse(reservationData.getDate()))
                    .number(Math.min(reservationData.getNumber(), 999))
                    .build());
        }
    }

    @Override
    public ReservationDateResDTO getReservationDateByMonth(YearMonth yearMonth) {
        List<String> dates = baseMapper.getReservationDate(yearMonth.atDay(1), yearMonth.atEndOfMonth());
        return new ReservationDateResDTO(dates);
    }

    @Override
    public void plusReservationCount(LocalDate time, Integer count) {
        if (!SqlHelper.retBool(baseMapper.plusReservationCount(time, count))) {
            throw new CommonException("预约人数已满不能预约");
        }
    }
}